import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:get/get.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:ball_lion/resources/colours.dart';
import 'package:ball_lion/utils/file_utils.dart';
import 'package:ball_lion/utils/toast_utils.dart';
import 'package:ball_lion/widgets/base/wqs_dialog.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';

class ImageUtils {
  static Future<String?> cropImage(String path) async {
    final croppedFile = await ImageCropper().cropImage(
      compressQuality: 50,
      sourcePath: path,
      aspectRatio: const CropAspectRatio(ratioX: 1.0, ratioY: 1.0),
      uiSettings: [
        AndroidUiSettings(
            toolbarTitle: '裁剪',
            toolbarColor: Colours.main,
            toolbarWidgetColor: Colors.white,
            initAspectRatio: CropAspectRatioPreset.square,
            lockAspectRatio: true,
            hideBottomControls: true,
            aspectRatioPresets: [CropAspectRatioPreset.square]),
        IOSUiSettings(
            title: '',
            aspectRatioPickerButtonHidden: true,
            aspectRatioLockEnabled: true,
            resetAspectRatioEnabled: false,
            aspectRatioPresets: [CropAspectRatioPreset.square])
      ],
    );
    return croppedFile?.path;
  }

  static Future<XFile?> pickPhotoFromCamera({int imageQuality = 50}) async {
    AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo;
    bool higher32 = info.version.sdkInt >= 32;
    bool isHarmony = false;
    bool? request;
    if (!await Permission.camera.isGranted) {
      request = true;
      request = await Get.dialog(QsDialog.alert("权限请求",
          content: "我们需要[相机权限]使用您的相机拍摄图片", confirmText: "同意"));
    }
    if (request == false) return null;
    PermissionStatus check = await Permission.camera.request();
    if (check == PermissionStatus.granted) {
      return await ImagePicker()
          .pickImage(source: ImageSource.camera, imageQuality: 50);
    } else if (check == PermissionStatus.denied && (!higher32 || isHarmony)) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content: "在拍照过程中我们需要使用您的相机，请您在权限中开启[相机权限]", confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return null;
    } else if (check ==
        ((isHarmony || !higher32)
            ? PermissionStatus.denied
            : PermissionStatus.permanentlyDenied)) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content: "在拍照过程中我们需要使用您的相机，请您在权限中开启[相机权限]", confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return null;
    } else {
      return null;
    }
  }

  static Future<List<AssetEntity>?> pickPhotoFromGallery(
      {int maxPhotos = 1}) async {
    AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo;
    bool higher32 = info.version.sdkInt >= 32;
    bool isHarmony = false;
    bool? request;
    if (isHarmony || !higher32) {
      request = true;
      if (!await Permission.storage.isGranted) {
        request = await Get.dialog(QsDialog.alert("权限请求",
            content: "我们需要[访问存储权限]以上传您的图片，保证头像正常更新", confirmText: "同意"));
      }
    } else {
      request = true;
      if (!await Permission.photos.isGranted) {
        request = await Get.dialog(QsDialog.alert("权限请求",
            content: "我们需要[访问相册权限]以上传您的图片，保证头像正常更新", confirmText: "同意"));
      }
    }
    if (request == false) return null;
    PermissionStatus check = (isHarmony || !higher32)
        ? await Permission.storage.request()
        : await Permission.photos.request();
    if (check == PermissionStatus.granted) {
      return AssetPicker.pickAssets(Get.context!,
          pickerConfig: AssetPickerConfig(
              maxAssets: maxPhotos,
              themeColor: Colours.main,
              requestType: RequestType.image,
              textDelegate: const AssetPickerTextDelegate()));
    } else if (check == PermissionStatus.denied && (!higher32 || isHarmony)) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content: "我们需要上传您的图片，以保证头像正常更新，请您在权限中开启[访问相册权限]",
              confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return null;
    } else if (check == PermissionStatus.permanentlyDenied) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content: "我们需要上传您的图片，以保证头像正常更新，请您在权限中开启[访问相册权限]",
              confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return null;
    } else {
      return null;
    }
  }

  static Future<bool?> saveImageToGallery(
      {Uint8List? image, String? url}) async {
    AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo;
    bool higher32 = info.version.sdkInt >= 32;
    bool isHarmony = false;
    try {
      isHarmony = false;
    } catch (e) {
      isHarmony = false;
    }
    bool? request;
    if (isHarmony || !higher32) {
      request = true;
      if (!await Permission.storage.isGranted) {
        request = await Get.dialog(QsDialog.alert("权限请求",
            content: "我们需要[访问${higher32 ? "相册" : "存储"}权限]将图片保存到相册",
            confirmText: "同意"));
      }
    } else {
      request = true;
      if (!await Permission.photos.isGranted) {
        request = await Get.dialog(QsDialog.alert("权限请求",
            content: "我们需要[访问${higher32 ? "相册" : "存储"}权限]将图片保存到相册",
            confirmText: "同意"));
      }
    }
    if (request == false) return null;
    PermissionStatus check = (isHarmony || !higher32)
        ? await Permission.storage.request()
        : await Permission.photos.request();
    if (check == PermissionStatus.granted) {
      Uint8List imageBytes;
      if (image != null) {
        imageBytes = image;
      } else if (url != null) {
        CachedNetworkImage image = CachedNetworkImage(imageUrl: url);
        BaseCacheManager manager = image.cacheManager ?? DefaultCacheManager();
        File file = await manager.getSingleFile(image.imageUrl,
            headers: image.httpHeaders ?? {});
        imageBytes = await file.readAsBytes();
      } else {
        Toast.text("保存失败");
        return false;
      }
      try {
        Map map = await ImageGallerySaver.saveImage(imageBytes);
        log(jsonEncode(map));
        if (map["isSuccess"] == true) Toast.text("保存成功");
        return true;
      } catch (e) {
        log("$e");
        Toast.text("保存失败");
        return false;
      }
    } else if (check == PermissionStatus.denied && (!higher32 || isHarmony)) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content: "我们需要将图片保存到相册，请您在权限中开启[访问${higher32 ? "相册" : "存储"}权限]",
              confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return null;
    } else if (check == PermissionStatus.permanentlyDenied) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content:
                  "我们需要上传您的图片，以保证头像正常更新，请您在权限中开启[访问${higher32 ? "相册" : "存储"}权限]",
              confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return null;
    } else {
      return null;
    }
    return null;
  }

  static Future<bool> getLivePermission() async {
    AndroidDeviceInfo info = await DeviceInfoPlugin().androidInfo;
    bool higher32 = info.version.sdkInt >= 32;
    bool isHarmony = false;
    bool? request;
    if (!await Permission.camera.isGranted &&
        !await Permission.audio.isGranted) {
      request = true;
      request = await Get.dialog(QsDialog.alert("权限请求",
          content: "我们需要[相机权限]与[麦克风权限]进行直播", confirmText: "同意"));
    }
    if (request == false) return false;
    Map<Permission, PermissionStatus> check =
        await [Permission.camera, Permission.speech].request();
    if (check[Permission.camera] == PermissionStatus.granted &&
        check[Permission.speech] == PermissionStatus.granted) {
      return true;
    } else if (check[Permission.camera] == PermissionStatus.denied &&
        (!higher32 || isHarmony)) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content: "在直播过程中我们需要使用您的相机，请您在权限中开启[相机权限]", confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return false;
    } else if (check[Permission.speech] == PermissionStatus.denied) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content: "在直播过程中我们需要使用您的麦克风，请您在权限中开启[麦克风权限]", confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return false;
    } else if (check[Permission.camera] ==
        ((isHarmony || !higher32)
            ? PermissionStatus.denied
            : PermissionStatus.permanentlyDenied)) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content: "在直播过程中我们需要使用您的相机，请您在权限中开启[相机权限]", confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return false;
    } else if (check[Permission.speech] == PermissionStatus.permanentlyDenied) {
      await Get.dialog<bool>(QsDialog.alert("权限请求",
              content: "在直播过程中我们需要使用您的麦克风，请您在权限中开启[麦克风权限]", confirmText: "去开启"))
          .then((value) async {
        if (value == true) {
          bool go = await openAppSettings();
          if (!go) Toast.text("打开设置失败，请您手动开启权限");
        }
      });
      return false;
    } else {
      return false;
    }
  }

  static Future<XFile?> compressImage(String imagePath,
      {double targetSize = 5}) async {
    final image = File(imagePath);
    final length = image.lengthSync();
    int quality = 95;
    if (length > 10 * 1014 * 1024) {
      quality = 90;
    } else if (length > 15 * 1014 * 1024) {
      quality = 80;
    }
    String targetPath = await FileUtils.getTemporaryPath();
    targetPath += imagePath.split('/').last;
    final compressedImage = await FlutterImageCompress.compressAndGetFile(
        imagePath, targetPath,
        quality: quality);
    // final length1 = await compressedImage!.length();
    return compressedImage;
  }

  static Future<Uint8List?> getBytes(BuildContext context, ImageProvider img,
      {ImageByteFormat format = ImageByteFormat.rawRgba}) async {
    final imageStream = img.resolve(createLocalImageConfiguration(context));
    final Completer<Uint8List?> completer = Completer<Uint8List?>();
    final ImageStreamListener listener = ImageStreamListener(
      (imageInfo, synchronousCall) async {
        final bytes = await imageInfo.image.toByteData(format: format);
        if (!completer.isCompleted) {
          completer.complete(bytes?.buffer.asUint8List());
        }
      },
    );
    imageStream.addListener(listener);
    final imageBytes = await completer.future;
    imageStream.removeListener(listener);
    return imageBytes;
  }
}
